
#include "../../Command.h"

#include "../../engine.h"

#include "../../User.h"

#include "../../NLogic/Static.h"
#include "../../NLogic/Battle.h"


namespace ProjectZ { namespace NCommand {

void SendResultToMe(User *pUser, NLogic::Party * pParty, int ack, int result)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<uint16_t>(ack);
	*pAck << static_cast<uint8_t>(result);

	if (ack != ACK_OK)
	{
		*pAck << static_cast<uint8_t>(pParty->GetAcceptUserTree().size());
	}
	else
	{
		*pAck << static_cast<uint8_t>(pParty->GetAcceptUserTree().size()-1);
	}
	std::for_each(pParty->GetAcceptUserTree().begin(), pParty->GetAcceptUserTree().end(), [&](const std::pair<int, User *> & pair) {
		if ( pair.first != pUser->GetUserSeq() )
		{
			*pAck << pair.first;
		}
	} );
	pAck->MakePacket(CMD_SC_PK_INVITATION_RESULT);
	pUser->Send(pAck);
}

void SendResultToOthers(User *pUser, NLogic::Party * pParty, int ack, int result)
{
	::Network::Packet * pOtherAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pOtherAck << static_cast<uint16_t>(ack);
	*pOtherAck << static_cast<uint8_t>(result);
	*pOtherAck << static_cast<uint8_t>(1);
	*pOtherAck << pUser->GetUserSeq();
	pOtherAck->MakePacket(CMD_SC_PK_INVITATION_RESULT);
	std::for_each(pParty->GetAllUserTree().begin(), pParty->GetAllUserTree().end(), [&](const std::pair<int, User *> & pair) {
		if ( pair.first != pUser->GetUserSeq() )
		{
			pair.second->SendOneshotEncrypt(pOtherAck, 1);
		}
	} );

	::Network::GETPACKETPOOL()->SEND_DEL(pOtherAck);
}

void SendReqPKEnter(User *pUser, NLogic::Space * pBattleRoyal, uint32_t space_seq)
{
	int pos_x[4] = { 31*32, 42*32, 19*32, 10*32 };
	int pos_y[4] = { 13*32, 21*32, 27*32, 15*32 };
	int degree[4] = { 90, 180, 270, 0 };

	auto userTreeItr = pBattleRoyal->GetUserTree().begin();
	for ( int i = 0 ; userTreeItr != pBattleRoyal->GetUserTree().end() ; ++userTreeItr, i++ )
	{
		User * pOther = userTreeItr->second;
		pOther->Set_PK_Coordinate( pos_x[i], pos_y[i], degree[i] );
	}

	::Network::Packet * pNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
	* pNoti << static_cast<uint64_t>(space_seq);
	pNoti->MakePacket(CMD_SC_REQ_PK_ENTER);
	pUser->GetSpace()->SendAll(pNoti);
	pUser->GetParty()->SetState(NLogic::Party::State::PK_ENTER_WAIT);
}


void Command::CS_PK_INVITATION_RESULT(User * pUser, ::Network::Packet * pPacket)
{
/*
	C -> S
	/// 초대 수락 : 초대받기UI 에서 수락 또는 취소				0x1418
	CS_PK_INVITATION_RESULT
	{
		u8	u8_result;	/// 0: 취소, 1: 수락, 2: 타임아웃
		u32 	u32pk_seq;	 /// pk session seq
	}

	S -> C
	SC_PK_INVITATION_RESULT 						0x1419
	{
		// 서버가 전체에게

		u8	u8_result;	/// 0: 취소, 1: 수락, 2: 타임아웃

		// 서버에서 기존에 대기방에 있던 유저한테는 새 유저 정보를, 새로 입장하는 유저한테는 기존에 대기방에 있는 유저를 보내줌
		// 기존 유저 : 새로 입장하는 유저 정보 (1명)
		// 입장하는 유저 : 기존에 있던 유저 정보 (1명 이상)

		u8 	u8count;
		{
			u32	u32gid;	// SC_REQ_SOCIAL_INFO 로 정보 요청
		}
	}

	S -> C (all)
	SC_REQ_PK_ENTER		0x1403
	{
		u64	u64pk_match_seq;		// 매치 시퀀스
	}
*/

	STRESSLOG("%s", __FUNCTION__);

	NLogic::Space * pSpace = pUser->GetSpace();
	if ( NULL == pSpace )
	{
		NLogic::NFunction::SendExceptionNoSpace(pUser);
		pUser->SetEnumState(User::EnumState::__NONE__);
		DEBUGLOG("%s Space is NULL", __FUNCTION__);
		return;
	}

	// 파티 조회
	NLogic::Party * pParty = pUser->GetParty();
	if ( NULL == pParty )
	{
		NLogic::NFunction::SendExceptionNoParty(pUser);
		pUser->SetEnumState(User::EnumState::__NONE__);
		DEBUGLOG("%s party is NULL", __FUNCTION__);
		return;
	}

	if (pSpace->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		//pParty->LeaveUser(pUser);
		//pUser->SetEnumState(User::EnumState::__NONE__);
		DEBUGLOG("%s pSpace->GetData()._spaceType != NLogic::Space::SpaceType::WORLD", __FUNCTION__);
		return;
	}

	if (NLogic::Party::State::PK_CANCEL == pParty->GetState())
		return;

	PREPARE_PACKET;

	uint8_t result = 0;
	uint32_t space_seq = 0;
	* pPacket >> result >> space_seq;

	if (1 != result)
	{
		pParty->SetState(NLogic::Party::State::PK_CANCEL);
		return;
	}

	// 배틀로얄 Space 검색
	auto itr = NLogic::Static::Instance().GETSPACETREE().find(space_seq);
	if ( itr == NLogic::Static::Instance().GETSPACETREE().end() )
	{
		//pUser->SetEnumState(User::EnumState::__NONE__);
		NLogic::NFunction::SendExceptionNoSpace(pUser);
		pParty->LeaveUser(pUser);
		DEBUGLOG("%s %d Space is NULL", __FUNCTION__, __LINE__);
		return;
	}

	if (pParty->GetState() != NLogic::Party::State::PK_ACCEPT_WAIT)
	{
		SendResultToMe(pUser, pParty, ACK_START_BATTLE, result);
		//pUser->SetEnumState(User::EnumState::__NONE__);
		pParty->LeaveUser(pUser);
		DEBUGLOG("%s %d pParty->GetState() != NLogic::Party::State::PK_ACCEPT_WAIT", __FUNCTION__, __LINE__);
		return;
	}

	pSpace->LeaveUser(pUser);

	NLogic::Space * pBattleRoyal = itr->second;
	pBattleRoyal->EnterUser(pUser);

	pParty->AddAcceptUserTree(pUser);

	// 서버에서 기존에 대기방에 있던 유저한테는 새 유저 정보를
	SendResultToOthers(pUser, pParty,ACK_OK, result);

	// 새로 입장하는 유저한테는 기존에 대기방에 있는 유저를 보내줌
	SendResultToMe(pUser, pParty,ACK_OK, result);

	pUser->GetBattle()->GetData().bReadyFight = false;

	if (pParty->GetAcceptUserTree().size() >= static_cast<size_t>(MAX_PK_INVITE))
	{
		SendReqPKEnter(pUser, pBattleRoyal, space_seq);
	}
}


} /*NCommand*/ }  /*ProjectZ*/
